import numpy as np
import struct
import av
import pyaudio

from TestToolApi import Debug
from multiprocessing import Process, Queue as ProcQueue, Event, Lock
import multiprocessing.sharedctypes as mps
from typing import Optional
from ctypes import *
import time
import select
import asyncio
import traceback
import socket
import random


class ControlData(Structure):
    _fields_ = [('up', c_bool),
                ('down', c_bool),
                ('left', c_bool),
                ('right', c_bool),
                ('speed', c_float)]


class BaseData(Structure):
    _fields_ = [('bat', c_float),
                ('speed', c_float),
                ('signel', c_uint8),
                ('lit', c_float),
                ('dim', c_float),
                ('time', c_double)]


class MediaCaptureServer(Process):

    def __init__(self, logging=True, daemon=True):
        super(MediaCaptureServer, self).__init__(daemon=daemon)
        if logging:
            self.__mainDebugQueue = ProcQueue(10)
        else:
            self.__mainDebugQueue = None
        self.__mainDebug = Debug(self.__mainDebugQueue, True, "上位机系统-客户端模块-流媒体采集进程")
        self.__ErrorStatus = Event()
        self.__VideoEvent = Event()
        self.__AudioEvent = Event()
        # 以下是共享内存
        self.__videoLock = Lock()
        self.__audioLock = Lock()
        self.VIDEO_STATUS = mps.Value(c_bool, False, lock=self.__videoLock)
        self.VIDEO_DATA = mps.Array(c_char, size_or_initializer=1024, lock=self.__videoLock)
        self.AUDIO_STATUS = mps.Value(c_bool, False, lock=self.__audioLock)
        self.AUDIO_DATA = mps.Array(c_char, size_or_initializer=1024, lock=self.__audioLock)

    async def __videoGetTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入视频流采集器")
        videoStream = await asyncio.create_subprocess_shell(
            f"ffmpeg -f dshow -r 30 -s 640x480 -i video=\"Integrated Camera\" " +
            f"-b:v 500k -sc_threshold 499 -vprofile main -preset ultrafast -tune zerolatency " +
            f"-vcodec h264_amf -f h264 -",
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.DEVNULL,
            shell=True
        )
        while not self.__ErrorStatus.is_set():
            try:
                rawData = await videoStream.stdout.readexactly(1024)
                if not self.__VideoEvent.is_set():
                    await saveBuffer.put(rawData)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[视频流采集器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[视频流采集器] 该进程发生错误, 退出!")
                break
        videoStream.terminate()
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[视频流采集器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[视频流采集器] 总进程遇到错误, 退出该进程!")

    async def __audioGetTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入音频流采集器")
        audioStream = await asyncio.create_subprocess_shell(
            f"ffmpeg -f dshow -i audio=\"麦克风阵列 (Synaptics SmartAudio HD)\" " +
            f"-ac 2 -ar 48000 -b:a 500k -acodec libmp3lame -f mp3 -",
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.DEVNULL,
            shell=True
        )
        while not self.__ErrorStatus.is_set():
            try:
                rawData = await audioStream.stdout.readexactly(1024)
                if not self.__AudioEvent.is_set():
                    await saveBuffer.put(rawData)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流采集器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流采集器] 该进程发生错误, 退出!")
                break
        audioStream.terminate()
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流采集器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[音频流采集器] 总进程遇到错误, 退出该进程!")

    async def __videoPutTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入视频流输出器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.VIDEO_STATUS.value:
                    rawData = await saveBuffer.get()
                    self.VIDEO_DATA.value = rawData
                    self.VIDEO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)

            except Exception as e:
                self.__mainDebug.error(
                    f"[视频流输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[视频流输出器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[视频流输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[视频流输出器] 总进程遇到错误, 退出该进程!")

    async def __audioPutTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入音频流输出器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.AUDIO_STATUS.value:
                    rawData = await saveBuffer.get()
                    self.AUDIO_DATA.value = rawData
                    self.AUDIO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流输出器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[音频流输出器] 总进程遇到错误, 退出该进程!")

    def run(self) -> None:
        self.__mainDebug.info("正在初始化进程")

        async def main():
            videoBuffer = asyncio.Queue(30)
            audioBuffer = asyncio.Queue(30)
            videoGetTask = asyncio.create_task(self.__videoGetTask(videoBuffer))
            audioGetTask = asyncio.create_task(self.__audioGetTask(audioBuffer))
            videoPutTask = asyncio.create_task(self.__videoPutTask(videoBuffer))
            audioVideoPutTask = asyncio.create_task(self.__audioPutTask(audioBuffer))
            await asyncio.gather(
                videoGetTask, audioGetTask,
                videoPutTask, audioVideoPutTask
            )

        self.__mainDebug.info("进程开始运行")
        asyncio.run(main())
        self.__ErrorStatus.set()
        self.__mainDebug.warn("总进程遇到错误, 退出该进程!")

    def openServer(self):
        self.start()

    def closeServer(self):
        self.__ErrorStatus.set()

    def isOpened(self):
        return self.is_alive()

    def getDebugText(self):
        self.__mainDebug.getInfo()

    def isVideoOpened(self):
        return not self.__VideoEvent.is_set()

    def isAudioOpened(self):
        return not self.__AudioEvent.is_set()

    def setVideo(self, status: bool):
        if status:
            self.__VideoEvent.clear()
        else:
            self.__VideoEvent.set()

    def setAudio(self, status: bool):
        if status:
            self.__AudioEvent.clear()
        else:
            self.__AudioEvent.set()


class CenterConsumerServer(Process):

    def __init__(self,
                 videoSentAddr: tuple,
                 audioSentAddr: tuple,
                 controlDataSentAddr: tuple,
                 mainVideoRecvAddr: tuple,
                 subVideoRecvAddr: tuple,
                 audioRecvAddr: tuple,
                 baseDataRecvAddr: tuple,
                 logging=True,
                 daemon=True):
        super(CenterConsumerServer, self).__init__(daemon=daemon)
        if logging:
            self.__mainDebugQueue = ProcQueue(10)
        else:
            self.__mainDebugQueue = None
        self.__mainDebug = Debug(self.__mainDebugQueue, True, "上位机系统-客户端模块-中央传输进程")
        self.__ErrorStatus = Event()
        # 以下是要发送的共享内存
        self.__recvMainVideoLock = Lock()
        self.__recvSubVideoLock = Lock()
        self.__recvAudioLock = Lock()
        self.__recvBaseDataLock = Lock()
        self.__controlDataLock = Lock()
        self.VIDEO_STATUS: Optional[mps.Value] = None
        self.VIDEO_DATA: Optional[mps.Array] = None
        self.AUDIO_STATUS: Optional[mps.Value] = None
        self.AUDIO_DATA: Optional[mps.Array] = None
        self.CONTROL_STATUS: Optional[mps.Value] = mps.Value(c_bool, False, lock=self.__controlDataLock)
        self.CONTROL_DATA: Optional[mps.Value] = mps.Value(ControlData, False, False, False, False, 0.0,
                                                           lock=self.__controlDataLock)
        # 以下是要接收的共享内存
        self.RECV_MAIN_VIDEO_STATUS = mps.Value(c_bool, False, lock=self.__recvMainVideoLock)
        self.RECV_MAIN_VIDEO_DATA = mps.Array(c_char, size_or_initializer=1024, lock=self.__recvMainVideoLock)
        self.RECV_SUB_VIDEO_STATUS = mps.Value(c_bool, False, lock=self.__recvSubVideoLock)
        self.RECV_SUB_VIDEO_DATA = mps.Array(c_char, size_or_initializer=1024, lock=self.__recvSubVideoLock)
        self.RECV_AUDIO_STATUS = mps.Value(c_bool, False, lock=self.__recvAudioLock)
        self.RECV_AUDIO_DATA = mps.Array(c_char, size_or_initializer=1024, lock=self.__recvAudioLock)
        self.RECV_BASEDATA_STATUS: Optional[mps.Value] = mps.Value(c_bool, False, lock=self.__recvBaseDataLock)
        self.RECV_BASEDATA_DATA: Optional[mps.Value] = mps.Value(BaseData, 0.0, 0.0, 0, 0.0, 0.0, 0.00,
                                                                 lock=self.__recvBaseDataLock)
        # 以下是发送地址
        self.videoSentAddr = videoSentAddr
        self.audioSentAddr = audioSentAddr
        self.controlDataSentAddr = controlDataSentAddr
        # 以下是接收地址
        self.mainVideoRecvAddr = mainVideoRecvAddr
        self.subVideoRecvAddr = subVideoRecvAddr
        self.audioRecvAddr = audioRecvAddr
        self.baseDataRecvAddr = baseDataRecvAddr

    async def __videoSentTask(self, videoSocket: socket.socket, sentAddress: tuple):
        self.__mainDebug.info("已进入视频流发送器")
        while not self.__ErrorStatus.is_set():
            try:
                if self.VIDEO_STATUS.value:
                    rawData = self.VIDEO_DATA.value
                    self.VIDEO_STATUS.value = False
                    await asyncio.sleep(0)
                    videoSocket.sendto(rawData, sentAddress)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[视频流发送器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[视频流发送器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[视频流发送器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[视频流发送器] 总进程遇到错误, 退出该进程!")

    async def __audioSentTask(self, audioSocket: socket.socket, sentAddress: tuple):
        self.__mainDebug.info("已进入音频流发送器")
        while not self.__ErrorStatus.is_set():
            try:
                if self.AUDIO_STATUS.value:
                    rawData = self.AUDIO_DATA.value
                    self.AUDIO_STATUS.value = False
                    await asyncio.sleep(0)
                    audioSocket.sendto(rawData, sentAddress)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流发送器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流发送器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流发送器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[音频流发送器] 总进程遇到错误, 退出该进程!")

    async def __mainVideoRecvGetTask(self, mainVideoRecvSocket: socket.socket, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入主视频流接收器")
        while not self.__ErrorStatus.is_set():
            try:
                result, _, _ = select.select([mainVideoRecvSocket], [], [], 0)
                if len(result) == 0:
                    await asyncio.sleep(0)
                else:
                    rawData, _ = mainVideoRecvSocket.recvfrom(1024)
                    # print("MAIN_VIDEO_RECV_GET", len(rawData))
                    await saveBuffer.put(rawData)
            except Exception as e:
                self.__mainDebug.error(
                    f"[主视频流接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[主视频流接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[主视频流接收器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[主视频流接收器] 总进程遇到错误, 退出该进程!")

    async def __subVideoRecvGetTask(self, subVideoRecvSocket: socket.socket, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入子视频流接收器")
        while not self.__ErrorStatus.is_set():
            try:
                result, _, _ = select.select([subVideoRecvSocket], [], [], 0)
                if len(result) == 0:
                    await asyncio.sleep(0)
                else:
                    rawData, _ = subVideoRecvSocket.recvfrom(1024)
                    await saveBuffer.put(rawData)
            except Exception as e:
                self.__mainDebug.error(
                    f"[子视频流接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[子视频流接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[子视频流接收器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[子视频流接收器] 总进程遇到错误, 退出该进程!")

    async def __audioRecvGetTask(self, audioRecvSocket: socket.socket, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入音频流接收器")
        while not self.__ErrorStatus.is_set():
            try:
                result, _, _ = select.select([audioRecvSocket], [], [], 0)
                if len(result) == 0:
                    await asyncio.sleep(0)
                else:
                    rawData, _ = audioRecvSocket.recvfrom(1024)
                    await saveBuffer.put(rawData)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流接收器] 出现全局错误申请, 退出该进程!")
        # print(self.__ErrorStatus.is_set())
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[音频流接收器] 总进程遇到错误, 退出该进程!")

    async def __mainVideoRecvPutTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入接收主视频流输出器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.RECV_MAIN_VIDEO_STATUS.value:
                    rawData = await saveBuffer.get()
                    # print("MAIN_VIDEO_RECV_PUT", len(rawData))
                    self.RECV_MAIN_VIDEO_DATA.value = rawData
                    self.RECV_MAIN_VIDEO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[接收主视频流输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[接收主视频流输出器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[接收主视频流输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[接收主视频流输出器] 总进程遇到错误, 退出该进程!")

    async def __subVideoRecvPutTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入接收子视频流输出器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.RECV_SUB_VIDEO_STATUS.value:
                    rawData = await saveBuffer.get()
                    self.RECV_SUB_VIDEO_DATA.value = rawData
                    self.RECV_SUB_VIDEO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[接收子视频流输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[接收子视频流输出器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[接收子视频流输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[接收子视频流输出器] 总进程遇到错误, 退出该进程!")

    async def __audioRecvPutTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入接收音频流输出器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.RECV_AUDIO_STATUS.value:
                    rawData = await saveBuffer.get()
                    self.RECV_AUDIO_DATA.value = rawData
                    self.RECV_AUDIO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[接收音频流输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[接收音频流输出器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[接收音频流输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[接收音频流输出器] 总进程遇到错误, 退出该进程!")

    async def __controlDataSentTask(self, controlDataSentSocket: socket.socket, saveBuffer: asyncio.Queue,
                                    sentAddress: tuple):
        self.__mainDebug.info("已进入控制数据发送器")
        package = struct.Struct('< ? ? ? ? f')
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty():
                    rawData = await saveBuffer.get()
                    await asyncio.sleep(0)
                    rawData = list(rawData.values())
                    rawData = package.pack(*rawData)
                    controlDataSentSocket.sendto(rawData, sentAddress)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[控制数据发送器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[控制数据发送器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[控制数据发送器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[控制数据发送器] 总进程遇到错误, 退出该进程!")

    async def __baseDataRecvTask(self, baseDataRecvSocket: socket.socket, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入状态数据接收器")
        while not self.__ErrorStatus.is_set():
            try:
                result, _, _ = select.select([baseDataRecvSocket], [], [], 0)
                if len(result) == 0:
                    await asyncio.sleep(0)
                else:
                    rawData, _ = baseDataRecvSocket.recvfrom(1024)
                    await saveBuffer.put(rawData)
            except Exception as e:
                self.__mainDebug.error(
                    f"[状态数据接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[状态数据接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[状态数据接收器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[状态数据接收器] 总进程遇到错误, 退出该进程!")

    async def __controlDataGetTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入控制数据获取器")
        while not self.__ErrorStatus.is_set():
            try:
                if self.CONTROL_STATUS.value:
                    rawData = {
                        'up': self.CONTROL_DATA.up, 'down': self.CONTROL_DATA.down, 'left': self.CONTROL_DATA.left,
                        'right': self.CONTROL_DATA.right, 'speed': self.CONTROL_DATA.speed
                    }
                    self.CONTROL_STATUS.value = False
                    await saveBuffer.put(rawData)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[控制数据获取器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[控制数据获取器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[控制数据获取器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[控制数据获取器] 总进程遇到错误, 退出该进程!")

    async def __baseDataOutTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入状态数据输出器")
        package = struct.Struct('< f f B f f d')
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.RECV_BASEDATA_STATUS.value:
                    rawData = await saveBuffer.get()
                    rawData = package.unpack(rawData)
                    # print(rawData)
                    self.RECV_BASEDATA_DATA.bat = rawData[0]
                    self.RECV_BASEDATA_DATA.speed = rawData[1]
                    self.RECV_BASEDATA_DATA.signel = rawData[2]
                    self.RECV_BASEDATA_DATA.lit = rawData[3]
                    self.RECV_BASEDATA_DATA.dim = rawData[4]
                    self.RECV_BASEDATA_DATA.time = rawData[5]
                    self.RECV_BASEDATA_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[状态数据输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[状态数据输出器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[状态数据输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[状态数据输出器] 总进程遇到错误, 退出该进程!")

    def run(self) -> None:
        self.__mainDebug.info("正在初始化进程")
        asyncioLoop = asyncio.new_event_loop()

        videoSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        videoSentTask = asyncioLoop.create_task(self.__videoSentTask(videoSocket, self.videoSentAddr))

        audioSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        audioSentTask = asyncioLoop.create_task(self.__audioSentTask(audioSocket, self.audioSentAddr))

        mainVideoRecvSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        mainVideoRecvSocket.bind(self.mainVideoRecvAddr)
        mainVideoRecvBuffer = asyncio.Queue(50, loop=asyncioLoop)
        mainVideoRecvGetTask = asyncioLoop.create_task(self.__mainVideoRecvGetTask(mainVideoRecvSocket,
                                                                                   mainVideoRecvBuffer))

        subVideoRecvSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        subVideoRecvSocket.bind(self.subVideoRecvAddr)
        subVideoRecvBuffer = asyncio.Queue(50, loop=asyncioLoop)
        subVideoRecvGetTask = asyncioLoop.create_task(self.__subVideoRecvGetTask(subVideoRecvSocket,
                                                                                 subVideoRecvBuffer))

        audioRecvSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        audioRecvSocket.bind(self.audioRecvAddr)
        audioRecvBuffer = asyncio.Queue(50, loop=asyncioLoop)
        audioRecvGetTask = asyncioLoop.create_task(self.__audioRecvGetTask(audioRecvSocket,
                                                                           audioRecvBuffer))

        mainVideoRecvPutTask = asyncioLoop.create_task(self.__mainVideoRecvPutTask(mainVideoRecvBuffer))
        subVideoRecvPutTask = asyncioLoop.create_task(self.__subVideoRecvPutTask(subVideoRecvBuffer))
        audioRecvPutTask = asyncioLoop.create_task(self.__audioRecvPutTask(audioRecvBuffer))

        controlDataBuffer = asyncio.Queue(50, loop=asyncioLoop)
        controlDataGetTask = asyncioLoop.create_task(self.__controlDataGetTask(controlDataBuffer))

        controlDataSentSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        controlDataSentTask = asyncioLoop.create_task(self.__controlDataSentTask(controlDataSentSocket,
                                                                                 controlDataBuffer,
                                                                                 self.controlDataSentAddr))

        baseDataBuffer = asyncio.Queue(50, loop=asyncioLoop)
        baseDataRecvSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        baseDataRecvSocket.bind(self.baseDataRecvAddr)
        baseDataRecvTask = asyncioLoop.create_task(self.__baseDataRecvTask(baseDataRecvSocket, baseDataBuffer))
        baseDataOutTask = asyncioLoop.create_task(self.__baseDataOutTask(baseDataBuffer))

        async def main():
            await asyncio.gather(
                videoSentTask, audioSentTask, mainVideoRecvGetTask, subVideoRecvGetTask, audioRecvGetTask,
                mainVideoRecvPutTask, subVideoRecvPutTask, audioRecvPutTask, controlDataGetTask, controlDataSentTask,
                baseDataRecvTask, baseDataOutTask
            )

        self.__mainDebug.info("进程开始运行")
        asyncioLoop.run_until_complete(main())
        self.__ErrorStatus.set()
        self.__mainDebug.warn("总进程遇到错误，退出该进程!")

    def openServer(self):
        self.start()

    def closeServer(self):
        self.__ErrorStatus.set()

    def isOpened(self):
        return self.is_alive()

    def getDebugText(self):
        self.__mainDebug.getInfo()


class AudioOutServer(Process):

    def __init__(self, logging=True, daemon=True):
        super(AudioOutServer, self).__init__(daemon=daemon)
        if logging:
            self.__mainDebugQueue = ProcQueue(10)
        else:
            self.__mainDebugQueue = None
        self.__mainDebug = Debug(self.__mainDebugQueue, True, "上位机系统-客户端模块-音频流输出进程")
        self.__ErrorStatus = Event()
        # 以下是要输出的共享内存
        self.RECV_AUDIO_STATUS: Optional[mps.Value] = None
        self.RECV_AUDIO_DATA: Optional[mps.Array] = None

    async def __audioOutRecvTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入音频流接收器")
        while not self.__ErrorStatus.is_set():
            try:
                if self.RECV_AUDIO_STATUS.value:
                    rawData = self.RECV_AUDIO_DATA.value
                    self.RECV_AUDIO_STATUS.value = False
                    await saveBuffer.put(rawData)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流接收器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        # print("错误")
        self.__mainDebug.warn("[音频流接收器] 总进程遇到错误, 退出该进程!")

    async def __audioOutEncodeTask(self, audioStream: asyncio.subprocess.Process, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入音频流解码器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty():
                    rawData = await saveBuffer.get()
                    audioStream.stdin.write(rawData)
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流解码器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流解码器] 该进程发生错误, 退出!")
                break
        audioStream.terminate()
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流解码器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[音频流解码器] 总进程遇到错误, 退出该进程!")

    async def __audioOutPutTask(self, audioStream: asyncio.subprocess.Process):
        self.__mainDebug.info("已进入音频流输出器")
        p = pyaudio.PyAudio()
        stream = p.open(
            format=pyaudio.paInt16,
            channels=2,
            rate=48000,
            output=True,
        )
        while not self.__ErrorStatus.is_set():
            try:
                rawData = await audioStream.stdout.readexactly(1024)
                stream.write(rawData)
                await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[音频流输出器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[音频流输出器] 该进程发生错误, 退出!")
                break
        audioStream.terminate()
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[音频流输出器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[音频流输出器] 总进程遇到错误, 退出该进程!")

    def run(self) -> None:
        self.__mainDebug.info("正在初始化进程")

        async def main():
            audioStream = await asyncio.create_subprocess_shell(
                f"ffmpeg -f mp3 -i - -f wav -",
                stdin=asyncio.subprocess.PIPE,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.DEVNULL,
                shell=True
            )

            audioOutBuffer = asyncio.Queue(50)
            audioOutRecvTask = asyncio.create_task(self.__audioOutRecvTask(audioOutBuffer))
            audioOutEncodeTask = asyncio.create_task(self.__audioOutEncodeTask(audioStream, audioOutBuffer))
            audioOutPutTask = asyncio.create_task(self.__audioOutPutTask(audioStream))
            await asyncio.gather(
                audioOutRecvTask, audioOutEncodeTask, audioOutPutTask
            )

        self.__mainDebug.info("进程开始运行")
        asyncio.run(main())
        self.__ErrorStatus.set()
        self.__mainDebug.warn("总进程遇到错误，退出该进程!")

    def openServer(self):
        self.start()

    def closeServer(self):
        self.__ErrorStatus.set()

    def isOpened(self):
        return self.is_alive()

    def getDebugText(self):
        self.__mainDebug.getInfo()


class MainVideoOutServer(Process):

    def __init__(self, logging=True, daemon=True):
        super(MainVideoOutServer, self).__init__(daemon=daemon)
        if logging:
            self.__mainDebugQueue = ProcQueue(10)
        else:
            self.__mainDebugQueue = None
        self.__mainDebug = Debug(self.__mainDebugQueue, True, "上位机系统-客户端模块-主视频流输出进程")
        self.__ErrorStatus = Event()
        self.__outVideoLock = Lock()
        # 以下是要输出的共享内存
        self.RECV_MAIN_VIDEO_STATUS: Optional[mps.Value] = None
        self.RECV_MAIN_VIDEO_DATA: Optional[mps.Array] = None
        # 以下是要编码的共享内存
        self.OUT_MAIN_VIDEO_STATUS = mps.Value(c_bool, False, lock=self.__outVideoLock)
        # print("开始")
        self.OUT_MAIN_VIDEO_DATA = mps.Array(c_char, size_or_initializer=480 * 640 * 3, lock=self.__outVideoLock)
        # self.OUT_MAIN_VIDEO_DATA = None
        # print(self.OUT_MAIN_VIDEO_DATA)

    async def __videoOutRecvTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入主视频流接收器")
        while not self.__ErrorStatus.is_set():
            try:
                if self.RECV_MAIN_VIDEO_STATUS.value:
                    rawData = self.RECV_MAIN_VIDEO_DATA.value
                    # print("MAIN_VIDEO_RECV_OUT", len(rawData))
                    self.RECV_MAIN_VIDEO_STATUS.value = False
                    await saveBuffer.put(rawData)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[主视频流接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[主视频流接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[主视频流接收器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[主视频流接收器] 总进程遇到错误, 退出该进程!")

    # async def __videoOutDecodeTask(self, saveInBuffer: asyncio.Queue, videoStream: asyncio.subprocess.Process):
    #     self.__mainDebug.info("已进入主视频流解码器")
    #     while not self.__ErrorStatus.is_set():
    #         try:
    #             if not saveInBuffer.empty():
    #                 rawDataIn = await saveInBuffer.get()
    #                 videoStream.stdin.write(rawDataIn)
    #                 await videoStream.stdin.drain()
    #             else:
    #                 await asyncio.sleep(0)
    #         except Exception as e:
    #             self.__mainDebug.error(
    #                 f"[主视频流解码器] \n{traceback.format_exc()}\n----------Error----------"
    #             )
    #             self.__mainDebug.error("[主视频流解码器] 该进程发生错误, 退出!")
    #             break
    #     if self.__ErrorStatus.is_set():
    #         self.__mainDebug.error("[主视频流解码器] 出现全局错误申请, 退出该进程!")
    #     self.__ErrorStatus.set()
    #     self.__mainDebug.warn("[主视频流解码器] 总进程遇到错误, 退出该进程!")

    async def __videoOutPutTask(self, saveInBuffer: asyncio.Queue, saveOutBuffer):
        self.__mainDebug.info("已进入主视频流生成器")
        codec = av.CodecContext.create('h264', 'r')
        while not self.__ErrorStatus.is_set():
            try:
                if not saveInBuffer.empty():
                    rawDataIn = await saveInBuffer.get()
                    # print("Incomming: ", len(rawDataIn))
                    packets = codec.parse(rawDataIn)
                    print(packets)
                    for packet in packets:
                        frames = codec.decode(packet)
                        for frame in frames:
                            frame = frame.reformat(format="bgr24")
                            frame = frame.to_ndarray()
                            await saveOutBuffer.put(frame)
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[主视频流生成器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[主视频流生成器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[主视频流生成器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[主视频流生成器] 总进程遇到错误, 退出该进程!")

    async def __videoOutFreshTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入图像更新器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.OUT_MAIN_VIDEO_STATUS.value:
                    rawData = await saveBuffer.get()
                    # print(len(rawData))
                    self.OUT_MAIN_VIDEO_DATA.value = rawData
                    self.OUT_MAIN_VIDEO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[图像更新器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[图像更新器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[图像更新器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[图像更新器] 总进程遇到错误, 退出该进程!")

    def run(self) -> None:
        self.__mainDebug.info("正在初始化进程")

        async def main():
            videoInBuffer = asyncio.Queue(50)
            videoOutBuffer = asyncio.Queue(50)

            # videoStream = await asyncio.create_subprocess_shell(
            #     f"ffmpeg -f h264 -i pipe: -vcodec h264 -pix_fmt bgr24 -f rawvideo pipe:",
            #     stdin=asyncio.subprocess.PIPE,
            #     # stdout=asyncio.subprocess.PIPE,
            #     shell=True
            # )

            videoOutRecvTask = asyncio.create_task(self.__videoOutRecvTask(videoInBuffer))
            # videoOutDecodeTask = asyncio.create_task(self.__videoOutDecodeTask(videoInBuffer, videoStream))
            videoOutPutTask = asyncio.create_task(self.__videoOutPutTask(videoInBuffer, videoOutBuffer))
            videoOutFreshTask = asyncio.create_task(self.__videoOutFreshTask(videoOutBuffer))
            await asyncio.gather(
                videoOutRecvTask, videoOutPutTask, videoOutFreshTask
            )

        self.__mainDebug.info("进程开始运行")
        asyncio.run(main())
        self.__ErrorStatus.set()
        self.__mainDebug.warn("总进程遇到错误，退出该进程!")

    def openServer(self):
        self.start()

    def closeServer(self):
        self.__ErrorStatus.set()

    def isOpened(self):
        return self.is_alive()

    def getDebugText(self):
        self.__mainDebug.getInfo()


class SubVideoOutServer(Process):

    def __init__(self, logging=True, daemon=True):
        super(SubVideoOutServer, self).__init__(daemon=daemon)
        if logging:
            self.__mainDebugQueue = ProcQueue(10)
        else:
            self.__mainDebugQueue = None
        self.__mainDebug = Debug(self.__mainDebugQueue, True, "上位机系统-客户端模块-子视频流输出进程")
        self.__ErrorStatus = Event()
        self.__outVideoLock = Lock()
        # 以下是要输出的共享内存
        self.RECV_SUB_VIDEO_STATUS: Optional[mps.Value] = None
        self.RECV_SUB_VIDEO_DATA: Optional[mps.Array] = None
        # 以下是要编码的共享内存
        self.OUT_SUB_VIDEO_STATUS = mps.Value(c_bool, False, lock=self.__outVideoLock)
        self.OUT_SUB_VIDEO_DATA = mps.Array(c_char, size_or_initializer=480 * 640 * 3, lock=self.__outVideoLock)
        # self.OUT_SUB_VIDEO_DATA = None

    async def __videoOutRecvTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入子视频流接收器")
        while not self.__ErrorStatus.is_set():
            try:
                if self.RECV_SUB_VIDEO_STATUS.value:
                    rawData = self.RECV_SUB_VIDEO_DATA.value
                    self.RECV_SUB_VIDEO_STATUS.value = False
                    await saveBuffer.put(rawData)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[子视频流接收器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[子视频流接收器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[子视频流接收器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[子视频流接收器] 总进程遇到错误, 退出该进程!")

    async def __videoOutDecodeTask(self, saveInBuffer: asyncio.Queue, videoStream: asyncio.subprocess.Process):
        self.__mainDebug.info("已进入子视频流解码器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveInBuffer.empty():
                    rawDataIn = await saveInBuffer.get()
                    videoStream.stdin.write(rawDataIn)
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[子视频流解码器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[子视频流解码器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[子视频流解码器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[子视频流解码器] 总进程遇到错误, 退出该进程!")

    async def __videoOutPutTask(self, saveOutBuffer: asyncio.Queue, videoStream: asyncio.subprocess.Process):
        self.__mainDebug.info("已进入子视频流生成器")
        while not self.__ErrorStatus.is_set():
            try:
                rawDataOut = await videoStream.stdout.readexactly(480 * 640 * 3)
                await saveOutBuffer.put(rawDataOut)
            except Exception as e:
                self.__mainDebug.error(
                    f"[子视频流生成器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[子视频流生成器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[子视频流生成器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[子视频流生成器] 总进程遇到错误, 退出该进程!")

    async def __videoOutFreshTask(self, saveBuffer: asyncio.Queue):
        self.__mainDebug.info("已进入图像更新器")
        while not self.__ErrorStatus.is_set():
            try:
                if not saveBuffer.empty() and not self.OUT_SUB_VIDEO_STATUS.value:
                    rawData = await saveBuffer.get()
                    self.OUT_SUB_VIDEO_DATA.value = rawData
                    self.OUT_SUB_VIDEO_STATUS.value = True
                    await asyncio.sleep(0)
                else:
                    await asyncio.sleep(0)
            except Exception as e:
                self.__mainDebug.error(
                    f"[图像更新器] \n{traceback.format_exc()}\n----------Error----------"
                )
                self.__mainDebug.error("[图像更新器] 该进程发生错误, 退出!")
                break
        if self.__ErrorStatus.is_set():
            self.__mainDebug.error("[图像更新器] 出现全局错误申请, 退出该进程!")
        self.__ErrorStatus.set()
        self.__mainDebug.warn("[图像更新器] 总进程遇到错误, 退出该进程!")

    def run(self) -> None:
        self.__mainDebug.info("正在初始化进程")

        async def main():
            videoStream = await asyncio.create_subprocess_shell(
                f"ffmpeg -f h264 -i - -f rawvideo -vcodec h264 -pix_fmt bgr24 -",
                stdin=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.DEVNULL,
                stdout=asyncio.subprocess.PIPE,
                shell=True
            )
            videoInBuffer = asyncio.Queue(50)
            videoOutBuffer = asyncio.Queue(50)

            videoOutRecvTask = asyncio.create_task(self.__videoOutRecvTask(videoInBuffer))
            videoOutDecodeTask = asyncio.create_task(self.__videoOutDecodeTask(videoInBuffer, videoStream))
            videoOutPutTask = asyncio.create_task(self.__videoOutPutTask(videoOutBuffer, videoStream))
            videoOutFreshTask = asyncio.create_task(self.__videoOutFreshTask(videoOutBuffer))
            await asyncio.gather(
                videoOutRecvTask, videoOutDecodeTask, videoOutPutTask, videoOutFreshTask
            )

        self.__mainDebug.info("进程开始运行")
        asyncio.run(main())
        self.__ErrorStatus.set()
        self.__mainDebug.warn("总进程遇到错误，退出该进程!")

    def openServer(self):
        self.start()

    def closeServer(self):
        self.__ErrorStatus.set()

    def isOpened(self):
        return self.is_alive()

    def getDebugText(self):
        self.__mainDebug.getInfo()


if __name__ == '__main__':
    SENT_IP = '139.155.181.21'
    RECV_IP = '0.0.0.0'

    mediaCaptureServer = MediaCaptureServer()
    mediaCaptureServer.setVideo(False)
    mediaCaptureServer.setAudio(False)
    centerConsumerServer = CenterConsumerServer(
        videoSentAddr=(SENT_IP, 6000),
        audioSentAddr=(SENT_IP, 6001),
        controlDataSentAddr=(SENT_IP, 6002),
        mainVideoRecvAddr=(RECV_IP, 8000),
        subVideoRecvAddr=(RECV_IP, 8001),
        audioRecvAddr=(RECV_IP, 8002),
        baseDataRecvAddr=(RECV_IP, 8003)
    )
    mainVideoOutServer = MainVideoOutServer()
    subVideoOutServer = SubVideoOutServer()
    audioOutServer = AudioOutServer()
    # 以上是进程初始化

    VIDEO_STATUS = mediaCaptureServer.VIDEO_STATUS
    VIDEO_DATA = mediaCaptureServer.VIDEO_DATA
    centerConsumerServer.VIDEO_STATUS = VIDEO_STATUS
    centerConsumerServer.VIDEO_DATA = VIDEO_DATA
    # 发送的视频流共享内存连接
    AUDIO_STATUS = mediaCaptureServer.AUDIO_STATUS
    AUDIO_DATA = mediaCaptureServer.AUDIO_DATA
    centerConsumerServer.AUDIO_STATUS = AUDIO_STATUS
    centerConsumerServer.AUDIO_DATA = AUDIO_DATA
    # 发送的音频流共享内存连接
    RECV_MAIN_VIDEO_STATUS = centerConsumerServer.RECV_MAIN_VIDEO_STATUS
    RECV_MAIN_VIDEO_DATA = centerConsumerServer.RECV_MAIN_VIDEO_DATA
    mainVideoOutServer.RECV_MAIN_VIDEO_STATUS = RECV_MAIN_VIDEO_STATUS
    mainVideoOutServer.RECV_MAIN_VIDEO_DATA = RECV_MAIN_VIDEO_DATA
    # 接收到的主视频流共享内存连接
    RECV_SUB_VIDEO_STATUS = centerConsumerServer.RECV_SUB_VIDEO_STATUS
    RECV_SUB_VIDEO_DATA = centerConsumerServer.RECV_SUB_VIDEO_DATA
    subVideoOutServer.RECV_SUB_VIDEO_STATUS = RECV_SUB_VIDEO_STATUS
    subVideoOutServer.RECV_SUB_VIDEO_DATA = RECV_SUB_VIDEO_DATA
    # 接收到的子视频流共享内存连接
    RECV_AUDIO_STATUS = centerConsumerServer.RECV_AUDIO_STATUS
    RECV_AUDIO_DATA = centerConsumerServer.RECV_AUDIO_DATA
    audioOutServer.RECV_AUDIO_STATUS = RECV_AUDIO_STATUS
    audioOutServer.RECV_AUDIO_DATA = RECV_AUDIO_DATA
    # 接收到的音频流共享内存连接

    # -------------- 以下是给客户端UI进程的共享内存 -------------- #
    RECV_BASEDATA_STATUS = centerConsumerServer.RECV_BASEDATA_STATUS
    RECV_BASEDATA_DATA = centerConsumerServer.RECV_BASEDATA_DATA
    # 下位机基础数据
    CONTROL_STATUS = centerConsumerServer.CONTROL_STATUS
    CONTROL_DATA = centerConsumerServer.CONTROL_DATA
    # 发给下位机的控制数据
    OUT_MAIN_VIDEO_STATUS = mainVideoOutServer.OUT_MAIN_VIDEO_STATUS
    OUT_MAIN_VIDEO_DATA = mainVideoOutServer.OUT_MAIN_VIDEO_DATA
    # 主视频流输出数据
    OUT_SUB_VIDEO_STATUS = subVideoOutServer.OUT_SUB_VIDEO_STATUS
    OUT_SUB_VIDEO_DATA = subVideoOutServer.OUT_SUB_VIDEO_DATA
    # 子视频流输出数据

    mediaCaptureServer.openServer()
    centerConsumerServer.openServer()
    mainVideoOutServer.openServer()
    subVideoOutServer.openServer()
    audioOutServer.openServer()

    mediaCaptureServer.join()
    centerConsumerServer.join()
    mainVideoOutServer.join()
    subVideoOutServer.join()
    audioOutServer.join()
